#include <math.h>
#include <stdio.h>
#include "report.h"
#include "uniform.h"

int main(int argc, char ** argv)
{
  UniformReal_t uni;
  UniformChoice_t unichoice;
  Report_Real_t stats;
  double avg, sd;
  int i;
  double sum;
  double x;

  /* decimal points are critical */
  UniformReal_Init_Params(&uni, 2, 12.5, 13.5);
  
  Report_Real_Init(&stats);
  
  for (i=0; i<100000; i++)
  {
    Report_Real_Update(&stats, UniformReal_Sample(&uni, 0));
  }

  Report_Real_Compute(&stats, &avg, &sd);

  if (fabs(avg - 13) > .1)
    return 1;
  
  if (fabs(sd*sd - (1.0/12.0)) > 1e-3)
    return 2;

  sum = 0;
  for (x=12.5; x<=13.5; x += .01)
  {
    sum += exp(UniformReal_LogProb(&uni, x, 0)) * .01;
  }
  
  if (fabs(sum - 1) > 1e-3)
  {
    printf("cum dist=%.4f\n", sum);
    return 3;
  }

  sum = 0;
  for (x=12.5; x<=13.5; x += .01)
  {
    sum += UniformReal_Prob(&uni, x, 0) * .01;
  }
  
  if (fabs(sum - 1) > 1e-3)
  {
    printf("cum dist=%.4f\n", sum);
    return 4;
  }

  /* UniformChoice */

  UniformChoice_Init_Params(&unichoice, 0);
  
  Report_Real_Init(&stats);
  
  for (i=0; i<100000; i++)
  {
    int val = UniformChoice_Sample(&unichoice, 1, 10);
    Report_Real_Update(&stats, val);
  }

  Report_Real_Compute(&stats, &avg, &sd);

  if (fabs(avg - 4.5) > .1)
    return 11;
  
  if (fabs(sd*sd - 8.25) > .1)
    return 12;

  sum = 0;
  for (x=0; x<10; x += 1)
  {
    sum += exp(UniformChoice_LogProb(&unichoice, x, 1, 10));
  }
  
  if (fabs(sum - 1) > 1e-3)
  {
    printf("cum dist=%.4f\n", sum);
    return 13;
  }

  sum = 0;
  for (x=0; x<10; x += 1)
  {
    sum += UniformChoice_Prob(&unichoice, x, 1, 10);
  }
  
  if (fabs(sum - 1) > 1e-3)
  {
    printf("cum dist=%.4f\n", sum);
    return 14;
  }

  if (UniformChoice_Sample(&unichoice, 1, 0) != -1)
    return 15;

  if (UniformChoice_LogProb(&unichoice, -1, 1, 0) != 0)
    return 16;
  
  if (UniformChoice_LogProb(&unichoice, 1, 1, 0) != -HUGE_VAL)
    return 17;

  if ((UniformChoice_Prob(&unichoice, -1, 1, 0) != 1)
      || (UniformChoice_Prob(&unichoice, 1, 1, 0) != 0))
    return 18;

  return 0;
}
